home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.5 Applications 2004 May / SGI IRIX 6.5 Applications 2004 May.iso / dist / java3d.idb / usr / demos / java / j3d / programs / examples / GearTest / SpurGear.java.z / SpurGear.java
Encoding:
Java Source  |  2003-08-08  |  21.8 KB  |  552 lines

  1. /*
  2.  *    @(#)SpurGear.java 1.18 02/04/01 15:03:17
  3.  *
  4.  * Copyright (c) 1996-2002 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * - Redistributions of source code must retain the above copyright
  11.  *   notice, this list of conditions and the following disclaimer.
  12.  *
  13.  * - Redistribution in binary form must reproduce the above copyright
  14.  *   notice, this list of conditions and the following disclaimer in
  15.  *   the documentation and/or other materials provided with the
  16.  *   distribution.
  17.  *
  18.  * Neither the name of Sun Microsystems, Inc. or the names of
  19.  * contributors may be used to endorse or promote products derived
  20.  * from this software without specific prior written permission.
  21.  *
  22.  * This software is provided "AS IS," without a warranty of any
  23.  * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
  24.  * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
  25.  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
  26.  * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
  27.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  28.  * DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
  29.  * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
  30.  * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
  31.  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
  32.  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE,
  33.  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  34.  *
  35.  * You acknowledge that Software is not designed,licensed or intended
  36.  * for use in the design, construction, operation or maintenance of
  37.  * any nuclear facility.
  38.  */
  39.  
  40. import java.lang.Math.*;
  41. import javax.media.j3d.*;
  42. import javax.vecmath.*;
  43.  
  44. public class SpurGear extends Gear {
  45.     
  46.     float toothTopAngleIncrement;
  47.     float toothDeclineAngleIncrement;
  48.  
  49.     float rootRadius;
  50.     float outsideRadius;
  51.  
  52.     //The angle subtended by the ascending or descending portion of a tooth
  53.     float circularToothEdgeAngle;
  54.     // The angle subtended by a flat (either a tooth top or a valley
  55.     // between teeth
  56.     float circularToothFlatAngle;
  57.  
  58.     /**
  59.      * internal constructor for SpurGear, used by subclasses to establish
  60.      * SpurGear's required state
  61.      * @return a new spur gear that contains sufficient information to
  62.      * continue building
  63.      * @param toothCount number of teeth
  64.      * @param pitchCircleRadius radius at center of teeth
  65.      * @param addendum distance from pitch circle to top of teeth
  66.      * @param dedendum distance from pitch circle to root of teeth
  67.      * @param toothToValleyAngleRatio the ratio of the angle subtended by the
  68.      * tooth to the angle subtended by the valley (must be <= .25) 
  69.      */
  70.     SpurGear(int toothCount, float pitchCircleRadius,
  71.          float addendum, float dedendum, float toothToValleyAngleRatio) {
  72.     
  73.     super(toothCount);
  74.     
  75.     // The angle about Z subtended by one tooth and its associated valley
  76.     circularPitchAngle = (float)(2.0 * Math.PI / (double)toothCount);
  77.  
  78.     // The angle subtended by a flat (either a tooth top or a valley
  79.     // between teeth
  80.     circularToothFlatAngle = circularPitchAngle * toothToValleyAngleRatio;
  81.  
  82.     //The angle subtended by the ascending or descending portion of a tooth
  83.     circularToothEdgeAngle = circularPitchAngle/2.0f -
  84.         circularToothFlatAngle;
  85.  
  86.     // Increment angles
  87.     toothTopAngleIncrement = circularToothEdgeAngle;
  88.     toothDeclineAngleIncrement
  89.         = toothTopAngleIncrement + circularToothFlatAngle;
  90.     toothValleyAngleIncrement
  91.         = toothDeclineAngleIncrement + circularToothEdgeAngle;
  92.  
  93.     // Differential angles for offsetting to the center of tooth's top
  94.     // and valley
  95.     toothTopCenterAngle
  96.         = toothTopAngleIncrement + circularToothFlatAngle/2.0f;
  97.     valleyCenterAngle
  98.         = toothValleyAngleIncrement +  circularToothFlatAngle/2.0f;
  99.  
  100.     // Gear start differential angle. All gears are constructed with the
  101.     // center of a tooth at Z-axis angle = 0.
  102.     gearStartAngle = -1.0 * toothTopCenterAngle;
  103.  
  104.     // The radial distance to the root and top of the teeth, respectively
  105.     rootRadius = pitchCircleRadius - dedendum;
  106.     outsideRadius = pitchCircleRadius + addendum;
  107.     
  108.     // Allow this object to spin. etc.
  109.     this.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  110.     }
  111.  
  112.     /**
  113.      * Construct a SpurGear;
  114.      * @return a new spur gear that conforms to the input paramters
  115.      * @param toothCount number of teeth
  116.      * @param pitchCircleRadius radius at center of teeth
  117.      * @param shaftRadius radius of hole at center
  118.      * @param addendum distance from pitch circle to top of teeth
  119.      * @param dedendum distance from pitch circle to root of teeth
  120.      * @param gearThickness  thickness of the gear
  121.      */
  122.     public SpurGear(int toothCount, float pitchCircleRadius, float shaftRadius,
  123.             float addendum, float dedendum, float gearThickness) {
  124.     this(toothCount, pitchCircleRadius, shaftRadius, addendum, dedendum,
  125.          gearThickness, gearThickness, 0.25f, null);
  126.     }
  127.  
  128.     /**
  129.      * Construct a SpurGear;
  130.      * @return a new spur gear that conforms to the input paramters
  131.      * @param toothCount number of teeth
  132.      * @param pitchCircleRadius radius at center of teeth
  133.      * @param shaftRadius radius of hole at center
  134.      * @param addendum distance from pitch circle to top of teeth
  135.      * @param dedendum distance from pitch circle to root of teeth
  136.      * @param gearThickness  thickness of the gear
  137.      * @param look the gear's appearance
  138.      */
  139.     public SpurGear(int toothCount, float pitchCircleRadius, float shaftRadius,
  140.             float addendum, float dedendum, float gearThickness,
  141.             Appearance look) {
  142.     this(toothCount, pitchCircleRadius, shaftRadius, addendum, dedendum,
  143.          gearThickness, gearThickness, 0.25f, look);
  144.     }
  145.  
  146.     /**
  147.      * Construct a SpurGear;
  148.      * @return a new spur gear that conforms to the input paramters
  149.      * @param toothCount number of teeth
  150.      * @param pitchCircleRadius radius at center of teeth
  151.      * @param shaftRadius radius of hole at center
  152.      * @param addendum distance from pitch circle to top of teeth
  153.      * @param dedendum distance from pitch circle to root of teeth
  154.      * @param gearThickness thickness of the gear
  155.      * @param toothTipThickness thickness of the tip of the tooth
  156.      * @param look the gear's appearance
  157.      */
  158.     public SpurGear(int toothCount, float pitchCircleRadius, float shaftRadius,
  159.             float addendum, float dedendum, float gearThickness,
  160.             float toothTipThickness, Appearance look) {
  161.     this(toothCount, pitchCircleRadius, shaftRadius, addendum, dedendum,
  162.          gearThickness, toothTipThickness, 0.25f, look);
  163.     }
  164.  
  165.     /**
  166.      * Construct a SpurGear;
  167.      * @return a new spur gear that conforms to the input paramters
  168.      * @param toothCount number of teeth
  169.      * @param pitchCircleRadius radius at center of teeth
  170.      * @param shaftRadius radius of hole at center
  171.      * @param addendum distance from pitch circle to top of teeth
  172.      * @param dedendum distance from pitch circle to root of teeth
  173.      * @param gearThickness thickness of the gear
  174.      * @param toothTipThickness thickness of the tip of the tooth
  175.      * @param toothToValleyAngleRatio the ratio of the angle subtended by the
  176.      * tooth to the angle subtended by the valley (must be <= .25) 
  177.      * @param look the gear's appearance object
  178.      */
  179.     public SpurGear(int toothCount, float pitchCircleRadius, float shaftRadius,
  180.             float addendum, float dedendum, float gearThickness,
  181.             float toothTipThickness, float toothToValleyAngleRatio,
  182.             Appearance look) {
  183.  
  184.     this(toothCount, pitchCircleRadius, addendum, dedendum,
  185.      toothToValleyAngleRatio);
  186.  
  187.     // Generate the gear's body disks
  188.     addBodyDisks(shaftRadius, rootRadius, gearThickness, look);
  189.     
  190.     // Generate the gear's interior shaft
  191.     addCylinderSkins(shaftRadius, gearThickness, InwardNormals, look);
  192.  
  193.     // Generate the gear's teeth
  194.     addTeeth(pitchCircleRadius, rootRadius,
  195.          outsideRadius, gearThickness, toothTipThickness,
  196.          toothToValleyAngleRatio, look);
  197.     }
  198.  
  199.     /**
  200.      * Construct a SpurGear's teeth by adding the teeth shape nodes
  201.      * @param pitchCircleRadius radius at center of teeth
  202.      * @param rootRadius distance from pitch circle to top of teeth
  203.      * @param outsideRadius distance from pitch circle to root of teeth
  204.      * @param gearThickness thickness of the gear
  205.      * @param toothTipThickness thickness of the tip of the tooth
  206.      * @param toothToValleyAngleRatio the ratio of the angle subtended by the
  207.      * tooth to the angle subtended by the valley (must be <= .25) 
  208.      * @param look the gear's appearance object
  209.      */
  210.     void addTeeth(float pitchCircleRadius, float rootRadius,
  211.           float outsideRadius, float gearThickness,
  212.           float toothTipThickness, float toothToValleyAngleRatio,
  213.           Appearance look) {
  214.     int index;
  215.     Shape3D newShape;
  216.     
  217.     // Temporaries that store start angle for each portion of tooth facet
  218.     double toothStartAngle, toothTopStartAngle,
  219.         toothDeclineStartAngle, toothValleyStartAngle,
  220.         nextToothStartAngle;
  221.  
  222.     // The x and y coordinates at each point of a facet and at each
  223.     // point on the gear: at the shaft, the root of the teeth, and
  224.     // the outer point of the teeth
  225.     float xRoot0, yRoot0;
  226.     float xOuter1, yOuter1;
  227.     float xOuter2, yOuter2;
  228.     float xRoot3, yRoot3;
  229.     float xRoot4, yRoot4;
  230.  
  231.     // The z coordinates for the gear
  232.     final float frontZ = -0.5f * gearThickness;
  233.     final float rearZ = 0.5f * gearThickness;
  234.  
  235.     // The z coordinates for the tooth tip of the gear
  236.     final float toothTipFrontZ = -0.5f * toothTipThickness;
  237.     final float toothTipRearZ = 0.5f * toothTipThickness;
  238.  
  239.     int toothFacetVertexCount;        // #(vertices) per tooth facet
  240.     int toothFacetCount;            // #(facets) per tooth
  241.     int toothFaceTotalVertexCount;          // #(vertices) in all teeth
  242.     int toothFaceStripCount[] = new int[toothCount];
  243.                         // per tooth vertex count
  244.     int topVertexCount;            // #(vertices) for teeth tops
  245.     int topStripCount[] = new int[1];    // #(vertices) in strip/strip
  246.  
  247.     // Front and rear facing normals for the teeth faces
  248.     Vector3f frontToothNormal = new Vector3f(0.0f, 0.0f, -1.0f);
  249.     Vector3f rearToothNormal = new Vector3f(0.0f, 0.0f, 1.0f);
  250.  
  251.     // Normals for teeth tops up incline, tooth top, and down incline
  252.     Vector3f leftNormal = new Vector3f(-1.0f, 0.0f, 0.0f);
  253.     Vector3f rightNormal = new Vector3f(1.0f, 0.0f, 0.0f);
  254.     Vector3f outNormal = new Vector3f(1.0f, 0.0f, 0.0f);
  255.     Vector3f inNormal = new Vector3f(-1.0f, 0.0f, 0.0f);
  256.  
  257.     // Temporary variables for storing coordinates and vectors 
  258.     Point3f coordinate = new Point3f(0.0f, 0.0f, 0.0f);
  259.     Point3f tempCoordinate1 = new Point3f(0.0f, 0.0f, 0.0f);
  260.     Point3f tempCoordinate2 = new Point3f(0.0f, 0.0f, 0.0f);
  261.     Point3f tempCoordinate3 = new Point3f(0.0f, 0.0f, 0.0f);
  262.     Vector3f tempVector1 = new Vector3f(0.0f, 0.0f, 0.0f);
  263.     Vector3f tempVector2 = new Vector3f(0.0f, 0.0f, 0.0f);
  264.  
  265.     /* Construct the gear's front facing teeth facets
  266.      *       0______2
  267.      *         /     /\
  268.      *        /   /    \
  269.      *       /  /       \
  270.      *      //___________\
  271.      *     1              3
  272.      */
  273.     toothFacetVertexCount = 4;
  274.     toothFaceTotalVertexCount = toothFacetVertexCount * toothCount;
  275.     for(int i = 0; i < toothCount; i++)
  276.         toothFaceStripCount[i] = toothFacetVertexCount;
  277.  
  278.     TriangleStripArray frontGearTeeth
  279.         = new TriangleStripArray(toothFaceTotalVertexCount,
  280.                      GeometryArray.COORDINATES
  281.                      | GeometryArray.NORMALS,
  282.                      toothFaceStripCount);
  283.  
  284.     for(int count = 0; count < toothCount; count++) {
  285.         index = count * toothFacetVertexCount;
  286.  
  287.         toothStartAngle
  288.         = gearStartAngle + circularPitchAngle * (double)count;
  289.         toothTopStartAngle = toothStartAngle + toothTopAngleIncrement;
  290.         toothDeclineStartAngle
  291.         = toothStartAngle + toothDeclineAngleIncrement;
  292.         toothValleyStartAngle
  293.         = toothStartAngle + toothValleyAngleIncrement;
  294.  
  295.         xRoot0 = rootRadius * (float)Math.cos(toothStartAngle);
  296.         yRoot0 = rootRadius * (float)Math.sin(toothStartAngle);
  297.         xOuter1 = outsideRadius * (float)Math.cos(toothTopStartAngle);
  298.         yOuter1 = outsideRadius * (float)Math.sin(toothTopStartAngle);
  299.         xOuter2 = outsideRadius * (float)Math.cos(toothDeclineStartAngle);
  300.         yOuter2 = outsideRadius * (float)Math.sin(toothDeclineStartAngle);
  301.         xRoot3 = rootRadius * (float)Math.cos(toothValleyStartAngle);
  302.         yRoot3 = rootRadius * (float)Math.sin(toothValleyStartAngle);
  303.     
  304.         tempCoordinate1.set(xRoot0, yRoot0, frontZ);
  305.         tempCoordinate2.set(xRoot3, yRoot3, frontZ);
  306.         tempVector1.sub(tempCoordinate2, tempCoordinate1);
  307.  
  308.         tempCoordinate2.set(xOuter1, yOuter1, toothTipFrontZ);
  309.         tempVector2.sub(tempCoordinate2, tempCoordinate1);
  310.  
  311.         frontToothNormal.cross(tempVector1, tempVector2);
  312.         frontToothNormal.normalize();
  313.  
  314.         coordinate.set(xOuter1, yOuter1, toothTipFrontZ);
  315.         frontGearTeeth.setCoordinate(index, coordinate);
  316.         frontGearTeeth.setNormal(index, frontToothNormal);
  317.  
  318.         coordinate.set(xRoot0, yRoot0, frontZ);
  319.         frontGearTeeth.setCoordinate(index + 1, coordinate);
  320.         frontGearTeeth.setNormal(index + 1, frontToothNormal);
  321.  
  322.         coordinate.set(xOuter2, yOuter2, toothTipFrontZ);
  323.         frontGearTeeth.setCoordinate(index + 2, coordinate);
  324.         frontGearTeeth.setNormal(index + 2, frontToothNormal);
  325.  
  326.         coordinate.set(xRoot3, yRoot3, frontZ);
  327.         frontGearTeeth.setCoordinate(index + 3, coordinate);
  328.         frontGearTeeth.setNormal(index + 3, frontToothNormal);
  329.     }
  330.     newShape = new Shape3D(frontGearTeeth, look);
  331.     this.addChild(newShape);
  332.  
  333.     /* Construct the gear's rear facing teeth facets (Using Quads)
  334.      *       1______2
  335.      *         /      \
  336.      *        /        \
  337.      *       /          \
  338.      *      /____________\
  339.      *     0              3
  340.      */
  341.     toothFacetVertexCount = 4;
  342.     toothFaceTotalVertexCount = toothFacetVertexCount * toothCount;
  343.  
  344.     QuadArray rearGearTeeth
  345.         = new QuadArray(toothCount * toothFacetVertexCount,
  346.                 GeometryArray.COORDINATES
  347.                 | GeometryArray.NORMALS);
  348.  
  349.     for(int count = 0; count < toothCount; count++) {
  350.  
  351.         index = count * toothFacetVertexCount;
  352.         toothStartAngle =
  353.         gearStartAngle + circularPitchAngle * (double)count;
  354.         toothTopStartAngle = toothStartAngle + toothTopAngleIncrement;
  355.         toothDeclineStartAngle
  356.         = toothStartAngle + toothDeclineAngleIncrement;
  357.         toothValleyStartAngle = toothStartAngle + toothValleyAngleIncrement;
  358.         
  359.         xRoot0 = rootRadius * (float)Math.cos(toothStartAngle);
  360.         yRoot0 = rootRadius * (float)Math.sin(toothStartAngle);
  361.         xOuter1 = outsideRadius * (float)Math.cos(toothTopStartAngle);
  362.         yOuter1 = outsideRadius * (float)Math.sin(toothTopStartAngle);
  363.         xOuter2 = outsideRadius * (float)Math.cos(toothDeclineStartAngle);
  364.         yOuter2 = outsideRadius * (float)Math.sin(toothDeclineStartAngle);
  365.         xRoot3 = rootRadius * (float)Math.cos(toothValleyStartAngle);
  366.         yRoot3 = rootRadius * (float)Math.sin(toothValleyStartAngle);
  367.  
  368.         tempCoordinate1.set(xRoot0, yRoot0, rearZ);
  369.         tempCoordinate2.set(xRoot3, yRoot3, rearZ);
  370.         tempVector1.sub(tempCoordinate2, tempCoordinate1);
  371.         tempCoordinate2.set(xOuter1, yOuter1, toothTipRearZ);
  372.         tempVector2.sub(tempCoordinate2, tempCoordinate1);
  373.         rearToothNormal.cross(tempVector2, tempVector1);
  374.         rearToothNormal.normalize();
  375.  
  376.         coordinate.set(xRoot0, yRoot0, rearZ);
  377.         rearGearTeeth.setCoordinate(index, coordinate);
  378.         rearGearTeeth.setNormal(index, rearToothNormal);
  379.  
  380.         coordinate.set(xOuter1, yOuter1, toothTipRearZ);
  381.         rearGearTeeth.setCoordinate(index + 1, coordinate);
  382.         rearGearTeeth.setNormal(index + 1, rearToothNormal);
  383.  
  384.         coordinate.set(xOuter2, yOuter2, toothTipRearZ);
  385.         rearGearTeeth.setCoordinate(index + 2, coordinate);
  386.         rearGearTeeth.setNormal(index + 2, rearToothNormal);
  387.  
  388.         coordinate.set(xRoot3, yRoot3, rearZ);
  389.         rearGearTeeth.setCoordinate(index + 3, coordinate);
  390.         rearGearTeeth.setNormal(index + 3, rearToothNormal);
  391.  
  392.     }
  393.     newShape = new Shape3D(rearGearTeeth, look);
  394.     this.addChild(newShape);
  395.  
  396.     /*
  397.      * Construct the gear's top teeth faces   (As seen from above)
  398.      *    Root0    Outer1    Outer2    Root3    Root4 (RearZ)
  399.      *    0_______3 2_______5 4_______7 6_______9
  400.      *      |0     3| |4     7| |8    11| |12   15|
  401.      *      |       | |       | |       | |       |
  402.      *      |       | |       | |       | |       |
  403.      *      |1_____2| |5_____6| |9____10| |13___14|
  404.      *      1       2 3       4 5       6 7       8
  405.      *    Root0    Outer1    Outer2    Root3    Root4 (FrontZ)
  406.      *
  407.      * Quad 0123 uses a left normal
  408.      * Quad 2345 uses an out normal
  409.      * Quad 4567 uses a right normal
  410.      * Quad 6789 uses an out normal
  411.      */
  412.     topVertexCount = 8 * toothCount + 2;
  413.     topStripCount[0] = topVertexCount;
  414.  
  415.     toothFacetVertexCount = 4;
  416.     toothFacetCount = 4;
  417.  
  418.     QuadArray topGearTeeth
  419.         = new QuadArray(toothCount * toothFacetVertexCount
  420.                 * toothFacetCount,
  421.                 GeometryArray.COORDINATES
  422.                 | GeometryArray.NORMALS);
  423.  
  424.     for(int count = 0; count < toothCount; count++) {
  425.         index = count * toothFacetCount * toothFacetVertexCount;
  426.         toothStartAngle = gearStartAngle +
  427.         circularPitchAngle * (double)count;
  428.         toothTopStartAngle = toothStartAngle + toothTopAngleIncrement;
  429.         toothDeclineStartAngle
  430.         = toothStartAngle + toothDeclineAngleIncrement;
  431.         toothValleyStartAngle
  432.         = toothStartAngle + toothValleyAngleIncrement;
  433.         nextToothStartAngle = toothStartAngle + circularPitchAngle;
  434.  
  435.         xRoot0 = rootRadius * (float)Math.cos(toothStartAngle);
  436.         yRoot0 = rootRadius * (float)Math.sin(toothStartAngle);
  437.         xOuter1 = outsideRadius * (float)Math.cos(toothTopStartAngle);
  438.         yOuter1 = outsideRadius * (float)Math.sin(toothTopStartAngle);
  439.         xOuter2 = outsideRadius * (float)Math.cos(toothDeclineStartAngle);
  440.         yOuter2 = outsideRadius * (float)Math.sin(toothDeclineStartAngle);
  441.         xRoot3 = rootRadius * (float)Math.cos(toothValleyStartAngle);
  442.         yRoot3 = rootRadius * (float)Math.sin(toothValleyStartAngle);
  443.         xRoot4 = rootRadius * (float)Math.cos(nextToothStartAngle);
  444.         yRoot4 = rootRadius * (float)Math.sin(nextToothStartAngle);
  445.  
  446.         // Compute normal for quad 1
  447.         tempCoordinate1.set(xRoot0, yRoot0, frontZ);
  448.         tempCoordinate2.set(xOuter1, yOuter1, toothTipFrontZ);
  449.         tempVector1.sub(tempCoordinate2, tempCoordinate1);
  450.         leftNormal.cross(frontNormal, tempVector1);
  451.         leftNormal.normalize();
  452.         
  453.         // Coordinate labeled 0 in the quad
  454.         coordinate.set(xRoot0, yRoot0, rearZ);
  455.         topGearTeeth.setCoordinate(index, coordinate);
  456.         topGearTeeth.setNormal(index, leftNormal);
  457.  
  458.         // Coordinate labeled 1 in the quad
  459.         coordinate.set(tempCoordinate1);
  460.         topGearTeeth.setCoordinate(index + 1, coordinate);
  461.         topGearTeeth.setNormal(index + 1, leftNormal);
  462.  
  463.         // Coordinate labeled 2 in the quad
  464.         topGearTeeth.setCoordinate(index + 2, tempCoordinate2);
  465.         topGearTeeth.setNormal(index + 2, leftNormal);
  466.         topGearTeeth.setCoordinate(index + 5, tempCoordinate2);
  467.  
  468.         // Coordinate labeled 3 in the quad
  469.         coordinate.set(xOuter1, yOuter1, toothTipRearZ);
  470.         topGearTeeth.setCoordinate(index + 3, coordinate);
  471.         topGearTeeth.setNormal(index + 3, leftNormal);
  472.         topGearTeeth.setCoordinate(index + 4, coordinate);
  473.  
  474.         // Compute normal for quad 2
  475.         tempCoordinate1.set(xOuter1, yOuter1, toothTipFrontZ);
  476.         tempCoordinate2.set(xOuter2, yOuter2, toothTipFrontZ);
  477.         tempVector1.sub(tempCoordinate2, tempCoordinate1);
  478.         outNormal.cross(frontNormal, tempVector1);
  479.         outNormal.normalize();
  480.  
  481.         topGearTeeth.setNormal(index + 4, outNormal);
  482.         topGearTeeth.setNormal(index + 5, outNormal);
  483.  
  484.         // Coordinate labeled 4 in the quad
  485.         topGearTeeth.setCoordinate(index + 6, tempCoordinate2);
  486.         topGearTeeth.setNormal(index + 6, outNormal);
  487.         topGearTeeth.setCoordinate(index + 9, tempCoordinate2);
  488.  
  489.         // Coordinate labeled 5 in the quad
  490.         coordinate.set(xOuter2, yOuter2, toothTipRearZ);
  491.         topGearTeeth.setCoordinate(index + 7, coordinate);
  492.         topGearTeeth.setNormal(index + 7, outNormal);
  493.         topGearTeeth.setCoordinate(index + 8, coordinate);
  494.  
  495.         // Compute normal for quad 3
  496.         tempCoordinate1.set(xOuter2, yOuter2, toothTipFrontZ);
  497.         tempCoordinate2.set(xRoot3, yRoot3, frontZ);
  498.         tempVector1.sub(tempCoordinate2, tempCoordinate1);
  499.         rightNormal.cross(frontNormal, tempVector1);
  500.         rightNormal.normalize();
  501.  
  502.         topGearTeeth.setNormal(index + 8, rightNormal);
  503.         topGearTeeth.setNormal(index + 9, rightNormal);
  504.  
  505.         // Coordinate labeled 7 in the quad
  506.         topGearTeeth.setCoordinate(index + 10, tempCoordinate2);
  507.         topGearTeeth.setNormal(index + 10, rightNormal);
  508.         topGearTeeth.setCoordinate(index + 13, tempCoordinate2);
  509.     
  510.         // Coordinate labeled 6 in the quad
  511.         coordinate.set(xRoot3, yRoot3, rearZ);
  512.         topGearTeeth.setCoordinate(index + 11, coordinate);
  513.         topGearTeeth.setNormal(index + 11, rightNormal);
  514.         topGearTeeth.setCoordinate(index + 12, coordinate);
  515.  
  516.         // Compute normal for quad 4
  517.         tempCoordinate1.set(xRoot3, yRoot3, frontZ);
  518.         tempCoordinate2.set(xRoot4, yRoot4, frontZ);
  519.         tempVector1.sub(tempCoordinate2, tempCoordinate1);
  520.         outNormal.cross(frontNormal, tempVector1);
  521.         outNormal.normalize();
  522.  
  523.         topGearTeeth.setNormal(index + 12, outNormal);
  524.         topGearTeeth.setNormal(index + 13, outNormal);
  525.  
  526.         // Coordinate labeled 9 in the quad
  527.         topGearTeeth.setCoordinate(index + 14, tempCoordinate2);
  528.         topGearTeeth.setNormal(index + 14, outNormal);
  529.  
  530.         // Coordinate labeled 8 in the quad
  531.         coordinate.set(xRoot4, yRoot4, rearZ);
  532.         topGearTeeth.setCoordinate(index + 15, coordinate);
  533.         topGearTeeth.setNormal(index + 15, outNormal);
  534.  
  535.         // Prepare for the loop by computing the new normal
  536.         toothTopStartAngle
  537.         = nextToothStartAngle + toothTopAngleIncrement;
  538.         xOuter1 = outsideRadius * (float)Math.cos(toothTopStartAngle);
  539.         yOuter1 = outsideRadius * (float)Math.sin(toothTopStartAngle);
  540.  
  541.         tempCoordinate1.set(xRoot4, yRoot4, toothTipFrontZ);
  542.         tempCoordinate2.set(xOuter1, yOuter1, toothTipFrontZ);
  543.         tempVector1.sub(tempCoordinate2, tempCoordinate1);
  544.         leftNormal.cross(frontNormal, tempVector1);
  545.         leftNormal.normalize();
  546.     }
  547.     newShape = new Shape3D(topGearTeeth, look);
  548.     this.addChild(newShape);
  549.     }
  550.  
  551. }
  552.